package com.weblog.article.service;

import com.weblog.article.client.UserClient;
import com.weblog.article.dao.CategoryDao;
import com.weblog.model.article.Category;
import com.weblog.article.utils.TreeOperationUtil;
import com.weblog.model.utils.CategoryTreeUtil;
import constants.RedisKey;
import entity.Result;
import exception.MyException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import util.IdWorker;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * category服务层
 *
 * @author Administrator
 */
@Service
public class CategoryService {

    @Autowired
    private CategoryDao categoryDao;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private UserClient userClient;

    @Autowired
    private RedisTemplate jsonRedisTemplate;

    @Autowired
    private TreeOperationUtil treeOperationUtil;

    /**
     * 添加分类
     *
     * @param category
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public int addCategory(Category category) {
        Category categoryByCname = categoryDao.findCategoryByCname(category.getCname());
        if(categoryByCname!=null){
            return 0;
        }
        if("".equals(category.getParentId())||category.getParentId()==null){
            //添加的是顶级类目
            category.setParentId("0");
            category.setClevel(1);
        }

        String token = (String) request.getAttribute("claims_admin_A");
        if (token != null && !"".equals(token)) {
            //普通管理员
            Result result = userClient.isAccess("role_category", "category_add");
            System.out.println("service:" + (int) result.getData());
            if ((int) result.getData() == 2) {
                //权限不足
                return 2;
            }
            handleAddCategory(category);
            return 1;

        }
        //超级管理员
            handleAddCategory(category);
        return 1;
    }

    /**
     * 添加分类操作
     * @param category
     */
    private void handleAddCategory(Category category){
        category.setId(idWorker.nextId() + "");
        category.setIsparent("0");

        if(!"0".equals(category.getParentId())){
            //添加的不是顶级节点
            //设置分类等级
            category.setClevel(categoryDao.findlevelById(category.getParentId())+1);

            if("0".equals(categoryDao.findById(category.getParentId()).get().getIsparent())){
                //父节点没有孩子
                categoryDao.updateIsparent("1",category.getParentId());
            }
            //移除缓存数据
        }
        categoryDao.save(category);
        jsonRedisTemplate.opsForList().leftPop(RedisKey.WEBLOG_CATEGORY_TREE);

    }



    /**
     * 条件查询+分页
     *
     * @param map
     * @param page
     * @param size
     * @return
     */
    public Page<Category> PageBySearch(Map<String, Object> map, int page, int size) {
        Specification<Category> specification = createSpecification(map);
        PageRequest pageRequest = PageRequest.of(page - 1, size);
        return categoryDao.findAll(specification, pageRequest);
    }


    /**
     * 条件查询?
     *
     * @param whereMap
     * @return
     */
    public List<Category> findSearch(Map whereMap) {
        Specification<Category> specification = createSpecification(whereMap);
        return categoryDao.findAll(specification);
    }

    /**
     * 根据ID查询实体
     *
     * @param id
     * @return
     */
    public Category findById(String id) {
        Category category = categoryDao.findById(id).get();
        if(category!=null){
            return category;
        }
        return null;
    }



    /**
     * 修改
     *
     * @param category
     */
    @Transactional(rollbackFor = MyException.class)
    public int update(Category category) {
        String token= (String) request.getAttribute("claims_admin_A");
        if(token!=null && !"".equals(token)){
            //普通管理员
            Result result = userClient.isAccess("role_category", "category_update");
            if((int)result.getData()==2){
                return 2;
            }

            treeOperationUtil.handleUpdate(category);
            //移除缓存数据
            jsonRedisTemplate.opsForList().leftPop(RedisKey.WEBLOG_CATEGORY_TREE);

            return 1;
        }
        treeOperationUtil.handleUpdate(category);
        //移除缓存数据
        jsonRedisTemplate.opsForList().leftPop(RedisKey.WEBLOG_CATEGORY_TREE);

        return 1;
    }



    /**
     * 删除
     *
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    public int deleteById(String id,String isparent) {
        String token= (String) request.getAttribute("claims_admin_A");
        if(token!=null && !"".equals(token)){
            //普通管理员
            Result result = userClient.isAccess("role_category", "category_delete");
            if((int)result.getData()==2){
                return 2;
            }
            treeOperationUtil.handleDelete(id,isparent);
            jsonRedisTemplate.opsForList().leftPop(RedisKey.WEBLOG_CATEGORY_TREE);
            return 1;
        }
        treeOperationUtil.handleDelete(id,isparent);
        jsonRedisTemplate.opsForList().leftPop(RedisKey.WEBLOG_CATEGORY_TREE);
        return 1;
    }




    /**
     * 动态条件构建
     *  TODO 改成vo实体
     * @param searchMap
     * @return
     */
    private Specification<Category> createSpecification(Map<String, Object> searchMap) {

        return new Specification<Category>() {

            @Override
            public Predicate toPredicate(Root<Category> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicateList = new ArrayList<Predicate>();

                // 分类名称
                if (searchMap.get("cname") != null && !"".equals(searchMap.get("cname"))) {
                    predicateList.add(cb.like(root.get("cname").as(String.class), "%" + (String) searchMap.get("cname") + "%"));
                }
                /**
                 * state：0弃用 1使用,2全部
                 *
                 */
                if (searchMap.get("state") != null && !"".equals(searchMap.get("state"))) {
                    String state = (String) searchMap.get("state");
                    if ("1".equals(state)) {
                        //查询可使用的分类
                        predicateList.add(cb.equal(root.get("state").as(String.class), (String) searchMap.get("state")));
                    }else if ("0".equals(state)) {
                        //查询弃用分类
                        predicateList.add(cb.equal(root.get("state").as(String.class), (String) searchMap.get("state")));
                    }
                }
                Predicate[] predicates = new Predicate[predicateList.size()];
                predicates = predicateList.toArray(predicates);
                return cb.and(predicates);
            }
        };
    }


    /**
     * 查询分类数据（树形）
     * @return
     */
    public List<Category> fetchCategoryTree() {
        List<Category> data=categoryDao.findByState("1");
        return CategoryTreeUtil.getTreeList("0",data);
    }

    /**
     * 查询总记录数
     * @return
     */
    public long count() {
        return  categoryDao.count();
    }

    /**
     * 根据id查询分类等级
     * @param cid
     * @return
     */
    public int findClevelById(String cid) {
       return categoryDao.findClevelById(cid);
    }
}
